package com.zrf.base.knowledge.classload.passive;

import java.util.function.Supplier;

public class NoInitialization {
    public static final Supplier<Boolean> SUB_PARENT_VALUE = () -> {
        /**
         * 代码运行完成后只会输出super class
         * 对于静态字段，只有定义这个字段的类才会被初始化。
         * 因此下面的代码只会初始化父类而不会触发子类的初始化
         */
        System.out.println("--------------------------");
        System.out.println(SubClass.value);
        System.out.println("--------------------------");
        return true;
    };

    public static final Supplier<Boolean> PARENT_ARRAY = () -> {
        /**
         * 下面的这段代码运行后没有输出superclass init
         * 真实初始化的是[L类的名称，由虚拟机生成的直接继承java.lang.Object的子类，创建动作指令由newarray触发
         */
        SuperClass[] superClasses = new SuperClass[10];
        return true;
    };

    public static final Supplier<Boolean> PARENT_FINAL_VALUE = () -> {
        /**
         *  类的public static final 基本类型变量也不会触发类的初始化，因为在编译阶段通过常量传播，已经将常量的值存储到了类的常量池中，常量的引用其实是引用的常量池中地址。
         */
        System.out.println("--------------------------");
        System.out.println(SuperClass.finalValue);
        System.out.println("--------------------------");
        return true;
    };

    public static final Supplier<Boolean> SUB_PARENT = ()-> {
        /**
         * 类的public static final 自定义类型会触发类的初始化
         * 自己的理解--》putstatic指令是在程序被编译后存放于类构造器中，所以parent是在类初始化阶段才执行的。初始化子类的时候发现父类未被
         * 加载，所以先加载父类，之后再加载子类
         */
        System.out.println("--------------------------");
        System.out.println(SubClass.parent);
        System.out.println("--------------------------");

        return true;
    };

    public static void main(String[] args) {
//        SUB_PARENT_VALUE.get();

//        PARENT_ARRAY.get();

//        PARENT_FINAL_VALUE.get();

        SUB_PARENT.get();
    }
}

class SubClass extends SuperClass {
    public static final SuperClass parent = new SuperClass();

    static {
        System.out.println("subClass init !!!!");
    }
}

class SuperClass {
    static {
        System.out.println("Super class init!!");
    }

    public static int value = 111;
    public static final int finalValue = 1111;
}